package main.java.FSMDE.models;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import main.java.ERMDE.infrastructure.Func;
import main.java.ERMDE.infrastructure.IterableExtensions;
import main.java.ERMDE.models.Diagram.DiagramState;
import main.java.FSMDE.models.Diagram;


public class Diagram {

	private UUID id;
	private InterfaceCollection interfaces;
	private TransitionCollection transitions;

	private List<Diagram> subDiagrams;
	private String name;
	@SuppressWarnings("unused")
	private DiagramState state;
	private boolean finalize;
	private List<String> subDiagramNames;

	public Diagram() {

		id = UUID.randomUUID();
		interfaces = new InterfaceCollection();
		transitions = new TransitionCollection();
		subDiagrams = new ArrayList<Diagram>();
		finalize = false;
		subDiagramNames = new ArrayList<String>();
	}

	public Diagram(InterfaceCollection interfaceCollection,
			TransitionCollection transitionCollection, List<Diagram> arrayList,
			boolean finalized) {

		id = UUID.randomUUID();
		interfaces = interfaceCollection;
		transitions = transitionCollection;
		subDiagrams = arrayList;
		finalize = finalized;
		subDiagramNames = new ArrayList<String>();
	}

	public void setInterfaces(InterfaceCollection interfaceCollection) {
		interfaces = interfaceCollection;
	}

	public InterfaceCollection getInterfaces() {
		return interfaces;
	}

	public void setTransitions(TransitionCollection transitionCollection) {
		transitions = transitionCollection;
	}

	public TransitionCollection getTransitions() {
		return transitions;
	}

	public void setSubDiagrams(List<Diagram> subDiagramList) {
		subDiagrams = subDiagramList;
	}

	public List<Diagram> getSubDiagrams() {
		return subDiagrams;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setId(UUID id) {
		this.id = id;
	}

	public UUID getId() {
		return id;
	}

	public Interface getInterface(UUID interfaceId) {
		return this.interfaces.get(interfaceId);
	}

	public boolean existsInterface(UUID id) {
		return (this.interfaces.get(id) != null);
	}

	public void removeInterface(UUID id) throws Exception {
		if (existsInterface(id)) {
			this.interfaces.remove(this.getInterface(id));
		} else {
			throw new Exception("Do not exists an Interface with id" + id);
		}
	}

	public void addSubDiagram(Diagram subDiagram) {
		this.subDiagrams.add(subDiagram);

	}

	public boolean existsSubDiagram(UUID id) {
		return IterableExtensions.firstOrDefault(this.subDiagrams,
				new SubDiagramsCompFunc(), id) != null;
	}

	public Diagram getSubDiagram(UUID id) {
		return IterableExtensions.firstOrDefault(this.subDiagrams,
				new SubDiagramsCompFunc(), id);
	}

	public void removeSubDiagram(UUID id) throws Exception {
		if (existsSubDiagram(id)) {
			this.subDiagrams.remove(this.getSubDiagram(id));
		} else {
			throw new Exception("Do not exists a SubDiagram with id" + id);
		}
	}

	private class SubDiagramsCompFunc extends Func<Diagram, UUID, Boolean> {
		@Override
		public Boolean execute(Diagram diagram, UUID id) {
			return diagram.getId().equals(id);
		}
	}

	public Transition getTransition(UUID transitionId) {
		return this.transitions.get(transitionId);
	}

	public boolean existsTransition(UUID id) {
		return (this.transitions.get(id) != null);
	}

	public void removeTransition(UUID id) throws Exception {
		if (existsTransition(id)) {
			this.transitions.remove(this.getTransition(id));
		} else {
			throw new Exception("Do not exists a Transition with id" + id);
		}
	}

	public void isNotValidated() {
		this.state = DiagramState.NotValidated;
	}

	public void isInvalid() {
		this.state = DiagramState.Invalid;
	}

	public void isValid() {
		this.state = DiagramState.Valid;
	}

	public boolean isFinalized() {
		return this.finalize;
	}

	public void finalizeDiagram() {
		/*
		 * switch(this.state){ case Invalid: finalize = false; //popup diagram
		 * is not valid!; break; case NotValidated: finalize = false; //popup
		 * diagram has not been validated! break; case Valid: //popup the
		 * diagram has been finalized successfully! break; }
		 */
		boolean finalized = true;
		for (Transition transition : transitions) {
			if (!transition.isEquilibrated()) {
				finalized = false;
			}
		}
		if (finalized) {
			this.finalize = true;
		}
	}

	public List<String> getSubDiagramNames() {
		return this.subDiagramNames;
	}

	@Override
	public String toString() {
		return this.name;
	}
}
